package api

import (
	"errors"
	"fanqiechaodan-blog/common"
	"fanqiechaodan-blog/config"
	"fanqiechaodan-blog/dao"
	"fanqiechaodan-blog/models"
	"fanqiechaodan-blog/service"
	"fanqiechaodan-blog/utils"
	"github.com/qiniu/go-sdk/v7/auth/qbox"
	"github.com/qiniu/go-sdk/v7/storage"
	"go.uber.org/zap"
	"net/http"
	"strconv"
	"strings"
	"time"
)

func (*Api) QiniuToken(writer http.ResponseWriter, request *http.Request) {
	// 判断当前是否登录,未登录无权限
	token := request.Header.Get("Authorization")
	_, _, err := utils.ParseToken(token)
	if err != nil {
		common.Error(writer, errors.New("未登录"))
		return
	}
	policy := storage.PutPolicy{Scope: "fanqiechaodanblog", Expires: 7200}
	mac := qbox.NewMac(config.Cfg.System.QiniuAccessKey, config.Cfg.System.QiniuSecretKey)
	res := policy.UploadToken(mac)
	common.Success(writer, res)
}

func (*Api) SearchPost(writer http.ResponseWriter, request *http.Request) {
	if err := request.ParseForm(); err != nil {
		common.Error(writer, errors.New("解析参数失败"))
		return
	}
	condition := request.FormValue("val")
	res, err := service.SearchPost(condition)
	if err != nil {
		common.Error(writer, errors.New("查询失败"))
		return
	}
	common.Success(writer, res)
}

func (*Api) GetPost(writer http.ResponseWriter, request *http.Request) {
	path := request.URL.Path
	pidStr := strings.TrimPrefix(path, "/api/v1/post/")
	pid, err := strconv.Atoi(pidStr)
	if err != nil {
		zap.S().Errorf("解析路由参数失败;路由:%s;err:%s", path, err.Error())
		common.Error(writer, errors.New("解析参数失败"))
		return
	}
	res, err := dao.GetPostDetailById(pid)
	if err != nil {
		common.Error(writer, errors.New("查询失败"))
		return
	}
	common.Success(writer, res)
}

func (*Api) SaveAndUpdatePost(writer http.ResponseWriter, request *http.Request) {
	// 判断当前是否登录,未登录无权限
	token := request.Header.Get("Authorization")
	_, claims, err := utils.ParseToken(token)
	if err != nil {
		common.Error(writer, errors.New("未登录"))
		return
	}
	uid := claims.Uid
	// 根据请求方式确认修改/保存
	method := request.Method
	params := common.GetRequestJSONParam(request)
	cid := params["categoryId"].(string)
	categoryId, err := strconv.Atoi(cid)
	if err != nil {
		zap.S().Errorf("解析categoryId参数异常,categoryId:%s,err:%s", cid, err.Error())
		common.Error(writer, errors.New("解析参数异常"))
		return
	}
	content := params["content"].(string)
	markdown := params["markdown"].(string)
	slug := params["slug"].(string)
	title := params["title"].(string)
	postType := (int)(params["type"].(float64))
	switch method {
	case http.MethodPost:
		// 保存
		post := &models.Post{
			Pid:        -1,
			Title:      title,
			Slug:       slug,
			Content:    content,
			Markdown:   markdown,
			CategoryId: categoryId,
			UserId:     uid,
			ViewCount:  0,
			Type:       postType,
			CreateAt:   time.Now(),
			UpdateAt:   time.Now(),
		}
		err := service.SavePost(post)
		if err != nil {
			zap.S().Errorf("发布文章失败;post:%+v,err:%s", post, err.Error())
			common.Error(writer, errors.New("发布文章失败"))
			return
		}
		common.Success(writer, post)
	case http.MethodPut:
		// 修改
		pid := int(params["pid"].(float64))
		postById, err := dao.GetPostDetailById(pid)
		if err != nil || postById.UserId != uid {
			zap.S().Errorf("不能修改不属于自己的文章;uid:%d,postUid:%d,err:%s", uid, postById.UserId, err.Error())
			common.Error(writer, errors.New("不能修改别人的文章"))
			return
		}
		post := &models.Post{
			Pid:        pid,
			Title:      title,
			Slug:       slug,
			Content:    content,
			Markdown:   markdown,
			CategoryId: categoryId,
			UserId:     uid,
			Type:       postType,
			UpdateAt:   time.Now(),
		}
		err = service.UpdatePost(post)
		if err != nil {
			zap.S().Errorf("编辑文章失败;post:%+v,err:%s", post, err.Error())
			common.Error(writer, errors.New("发布文章失败"))
			return
		}
		common.Success(writer, post)
	}
}

func (*Api) DeletePost(writer http.ResponseWriter, request *http.Request) {
	// 判断当前是否登录,未登录无权限
	token := request.Header.Get("Authorization")
	_, claims, err := utils.ParseToken(token)
	if err != nil {
		common.Error(writer, errors.New("未登录"))
		return
	}
	uid := claims.Uid
	path := request.URL.Path
	pidStr := strings.TrimPrefix(path, "/api/delete/v1/post/")
	pid, err := strconv.Atoi(pidStr)
	if err != nil {
		zap.S().Errorf("解析路由参数失败;路由:%s;err:%s", path, err.Error())
		common.Error(writer, errors.New("解析参数失败"))
		return
	}
	post, err := dao.GetPostDetailById(pid)
	if post.UserId != uid {
		common.Error(writer, errors.New("只能删除自己的文章"))
		return
	}
	err = dao.DeletePost(pid)
	if err != nil {
		zap.S().Errorf("删除失败;pid:%d,err:%s", pid, err.Error())
		common.Error(writer, errors.New("删除文章失败"))
		return
	}
	common.Success(writer, pid)
}
